package service;

import com.google.gson.Gson;
import config.ConfigLoader;
import config.RPC;
import entity.Transaction;

import javax.sql.DataSource;
import java.io.*;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;

@RPC
public class RPCServiceImpl implements RPCService {
    private Map<String, Double> cardBalances; // 保存卡号和余额的map

    @Override
    public String request(String json) {
        cardBalances = loadCardBalances(); // 初始化map

        Gson gson = new Gson();
        Transaction transaction = gson.fromJson(json, Transaction.class);
        String response = processTransaction(transaction);
        saveCardBalances();
        return response;
    }


    /**
     * 处理充值消费业务逻辑
     *
     * @param transaction 交易信息
     * @return responseMessage 处理结果
     */
    private String processTransaction(Transaction transaction) {
        if(transaction == null){
            return "输入格式不正确，请按照'类型 卡号 金额'的格式输入";
        }
        // 3.1 卡号不存在，创建并初始化余额为0
        cardBalances.putIfAbsent(transaction.getCardNumber(), 0.0);
        // 3.2 卡号存在，获取余额到balance变量
        double balance = cardBalances.get(transaction.getCardNumber());

        String responseMessage;
        // 3.3 根据交易类型进行处理
        // 3.3.1 消费
        if ("消费".equals(transaction.getType())) {
            if (balance >= transaction.getAmount()) {
                // 3.3.1.1 余额足，扣除map中的余额
                cardBalances.put(transaction.getCardNumber(), balance - transaction.getAmount());
                responseMessage = "消费成功，当前余额：" + (balance - transaction.getAmount());
            } else {
                // 3.3.1.2 余额不足，提示余额不足
                responseMessage = "消费失败，余额不足";
            }
        }
        // 3.3.2 充值
        else if ("充值".equals(transaction.getType())) {
            // 3.3.2.1 余额足，增加map中的余额
            cardBalances.put(transaction.getCardNumber(), balance + transaction.getAmount());
            responseMessage = "充值成功，当前余额：" + (balance + transaction.getAmount());
        } else {
            responseMessage = "操作失败，无效的操作类型";
        }
        // 服务端信息记录
        System.out.println("卡号 " + transaction.getCardNumber() + " 操作: " + transaction.getType() + "，金额: " + transaction.getAmount() + "。" + responseMessage);
        return responseMessage;
    }

    /**
     * 加载数据库中的卡号和余额信息
     *
     * @return 卡号和余额的map
     */
    private Map<String, Double> loadCardBalances() {
        Connection connection = RPCServiceImpl.getConnection();
        Map<String, Double> cardBalances = new HashMap<>();
        String sql = "SELECT cardId, amount FROM card";
        try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
            try (ResultSet resultSet = preparedStatement.executeQuery()) {
                while (resultSet.next()) {
                    String cardId = resultSet.getString("cardId");
                    double amount = resultSet.getDouble("amount");
                    cardBalances.put(cardId, amount);
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        return cardBalances;
    }

    /**
     * 保存卡号和余额到数据库
     */
    private void saveCardBalances() {
        // 遍历map中的数据，保存到数据库中
        Connection connection = RPCServiceImpl.getConnection();
        for (Map.Entry<String, Double> entry : cardBalances.entrySet()) {
            String sql = "INSERT INTO card (cardId, amount) VALUES (?, ?) ON DUPLICATE KEY UPDATE amount = VALUES(amount)";
            try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
                preparedStatement.setString(1, entry.getKey());
                preparedStatement.setDouble(2, entry.getValue());
                preparedStatement.executeUpdate();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 数据库连接对象
     */
    public static Connection getConnection() {
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(ConfigLoader.getMysqlUrl(), ConfigLoader.getMysqlUsername(), ConfigLoader.getMysqlPassword());
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }
}